/**
 * 
 */
package com.example.downloadmanagerdemo.download;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;

/**
 * @author careyjwang
 * 
 */
public class DownloadManager implements DownloadStatusCallback {
	private static DownloadManager sInstance;
	private ExecutorService mDownloadExecutor;
	private List<DownloadStatusCallback> mCallbacks;
	private HashMap<String, DownloadTask> mDownloadingTasks;
	private Context mContext;

	public static DownloadManager getInstance(Context context) {
		if (sInstance == null) {
			sInstance = new DownloadManager(context);
		}
		return sInstance;
	}

	private DownloadManager(Context context) {
		mDownloadExecutor = Executors.newFixedThreadPool(2);
		mCallbacks = new ArrayList<DownloadStatusCallback>();
		mDownloadingTasks = new HashMap<String, DownloadTask>();
		mContext = context;
	}

	public void addTask(DownloadTask task) {
		mDownloadingTasks.put(task.packageName(), task);
		task.setDownloadStatusCallback(this);
		mDownloadExecutor.execute(task);
	}

	public void startDownload(DownloadInfo info) {
		DownloadTask task = new DownloadTask(getDownloadDir(info), info);
		task.useMMCache(true);
		task.onPrepared();
		addTask(task);
	}

	public void pauseDownload(DownloadInfo info) {
		mDownloadingTasks.get(info.getPackageName()).cancel();
		mDownloadingTasks.remove(info.getPackageName());
	}

	public void resumeDownload(DownloadInfo info) {
		DownloadTask task = new DownloadTask(getDownloadDir(info), info);
		task.useMMCache(true);
		addTask(task);
	}

	public void cancelDownload(DownloadInfo info) {
		mDownloadingTasks.get(info.getPackageName()).cancel();
		mDownloadingTasks.remove(info.getPackageName());
		info.setDownloadState(DownloadStatus.STATUS_INIT);
		DownloadRecordHelper.getInstance().clearRecord(info.getPackageName());
	}

	public void pauseAll() {
		for (DownloadTask task : mDownloadingTasks.values()) {
			task.cancel();
			mDownloadingTasks.remove(task);
		}
	}

	public void registerDownloadCallback(DownloadStatusCallback callback) {
		mCallbacks.add(callback);
	}

	public void unRegisterDownloadCallback(DownloadStatusCallback callback) {
		mCallbacks.remove(callback);
	}

	@Override
	public synchronized void onDownloadStatusChanged(int status, String packageName) {
		for (DownloadStatusCallback callback : mCallbacks) {
			callback.onDownloadStatusChanged(status, packageName);
			if (status == DownloadStatus.STATUS_FAILED || status == DownloadStatus.STATUS_SUCCESS
					|| status == DownloadStatus.STATUS_PAUSE) {
				mDownloadingTasks.remove(packageName);
			}
		}
	}

	@Override
	public synchronized void onDownloadProgressChanged(int progress, String packageName) {
		for (DownloadStatusCallback callback : mCallbacks) {
			callback.onDownloadProgressChanged(progress, packageName);
		}
	}

	@Override
	public synchronized void onDownloadError(DownloadError error) {
		Log.e(DownloadConfig.LOG_TAG, error.toString());
		for (DownloadStatusCallback callback : mCallbacks) {
			callback.onDownloadError(error);
		}
	}

	private String getDownloadDir(DownloadInfo info) {
		File file = new File(DownloadConfig.DOWNLOAD_FILE_ROOT);
		if (!file.exists()) {
			Log.i(DownloadConfig.LOG_TAG, "mkdir" + file.mkdirs());
		}
		return DownloadConfig.DOWNLOAD_FILE_ROOT + File.separator + info.getPackageName() + info.getId();
	}

	public void install(DownloadInfo info) {
		try {
			File file = new File(getDownloadDir(info) + ".apk");
			Uri uri = Uri.fromFile(file);
			Intent intent = new Intent(Intent.ACTION_VIEW);
			intent.setDataAndType(uri, "application/vnd.android.package-archive");
			intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			mContext.startActivity(intent);
		} catch (Exception ex) {
		}
	}
}
